import gtk
import gobject

class CellRendererButton( gtk.CellRendererText ):
        __gproperties__ = { "callable": ( gobject.TYPE_PYOBJECT,
                                      "callable property",
                                      "callable property",
                                      gobject.PARAM_READWRITE ) }
        _button_width = 40
        _button_height = 30

        def __init__( self ):
                self.__gobject_init__()
                gtk.CellRendererText.__init__( self )
                self.set_property( "xalign", 0.5 )
                self.set_property( "mode", gtk.CELL_RENDERER_MODE_ACTIVATABLE )
                self.callable = None
                self.table = None
        # __init__()


        def do_set_property( self, pspec, value ):
                if pspec.name == "callable":
                        if callable( value ):
                                self.callable = value
                        else:
                                raise TypeError( "callable property must be callable!" )
                else:
                        raise AttributeError( "Unknown property %s" % pspec.name )
        # do_set_property()


        def do_get_property( self, pspec ):
                if pspec.name == "callable":
                        return self.callable
                else:
                        raise AttributeError( "Unknown property %s" % pspec.name )
        # do_get_property()


        def do_get_size( self, wid, cell_area ):
                xpad = self.get_property( "xpad" )
                ypad = self.get_property( "ypad" )

                if not cell_area:
                        x, y = 0, 0
                        w = 2 * xpad + self._button_width
                        h = 2 * ypad + self._button_height
                else:
                        w = 2 * xpad + cell_area.width
                        h = 2 * ypad + cell_area.height

                        xalign = self.get_property( "xalign" )
                        yalign = self.get_property( "yalign" )

                        x = max( 0, xalign * ( cell_area.width - w ) )
                        y = max( 0, yalign * ( cell_area.height - h ) )

                return ( x, y, w, h )
        # do_get_size()


        def do_render( self, window, wid, bg_area, cell_area, expose_area, flags ):
                if not window:
                        return

                xpad = self.get_property( "xpad" )
                ypad = self.get_property( "ypad" )

                x, y, w, h = self.get_size( wid, cell_area )

# if flags & gtk.CELL_RENDERER_SELECTED :
# state = gtk.STATE_ACTIVE
# shadow = gtk.SHADOW_OUT
                if flags & gtk.CELL_RENDERER_PRELIT :
                        state = gtk.STATE_PRELIGHT
                        shadow = gtk.SHADOW_ETCHED_OUT
                else :
                        state = gtk.STATE_NORMAL
                        shadow = gtk.SHADOW_OUT
                wid.get_style().paint_box( window, state, shadow, cell_area,
                                                         wid, "button",
                                                         cell_area.x + x + xpad,
                                                         cell_area.y + y + ypad,
                                                         w - 6, h - 6 )
                flags = flags & ~gtk.STATE_SELECTED
                gtk.CellRendererText.do_render( self, window, wid, bg_area,
                                                              (cell_area[0], cell_area[1] + ypad, cell_area[2],cell_area[3]), expose_area, flags )
    # do_render()

        def do_activate( self, event, wid, path, bg_area, cell_area, flags ):
                cb = self.get_property( "callable" )
                if cb != None :
                        cb (path)
                return True
# _CellRendererButton


gobject.type_register( CellRendererButton )


if __name__ == "__main__":

        class Tree(gtk.TreeView):
                def __init__(self):
                        self.store = gtk.ListStore(gobject.TYPE_STRING,
                                                                      gobject.TYPE_PYOBJECT)
                        gtk.TreeView.__init__(self)
                        self.set_size_request(300, 200)
                        self.set_model(self.store)
                        self.set_headers_visible(True)
                        #self.get_selection().set_mode(gtk.SELECTION_NONE)

                        rend = gtk.CellRendererText()
                        column = gtk.TreeViewColumn('First', rend, text=0)
                        self.append_column(column)

                        rend = CellRendererButton()
                        column = gtk.TreeViewColumn('Second', rend, text=0, callable=1)
                        self.append_column(column)        

                def insert(self, name):
                        iter = self.store.append()
                        self.store.set(iter, 0, name, 1, self.callback)

                def callback(self, path) :
                        print self,"callback()", path, self.store.get_value(self.store.get_iter(path), 0)

        w = gtk.Window()
        w.set_position(gtk.WIN_POS_CENTER)
        w.connect('delete-event', gtk.main_quit)
        t = Tree()
        t.insert('foo')
        t.insert('bar')
        t.insert('baz')
        w.add(t)

        w.show_all()
        gtk.main() 